//
//  PersonDataManager.m
//  trongvm
//
//  Created by Admin on 5/24/12.
//  Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//

#import "PersonDataManager.h"

#pragma mark - PersonNodeData

@implementation PersonNodeData
@synthesize personSmallAvatar, personMediumAvatar, personLargeAvatar, personGender, personID, personLargeAvatarURL, personMediumAvatarURL, personName, personSmallAvatarURL, titletext, title, subtitle, subtitletext, coordinate, isLocalCopyType, driverCapacity, driverLicense, driverVendor;

- (void)dealloc {
}

- (NSString *)subtitle {
	return subtitletext;
}
- (NSString *)title {
	return titletext;
}

- (void)setTitle:(NSString*)strTitle {
	self.titletext = strTitle;
}

- (void)setSubTitle:(NSString*)strSubTitle {
	self.subtitletext = strSubTitle;
}

- (id)initWithPersonName:(NSString *)strName
             andPersonID:(NSString *)strID
         andPersonSmallAvatar:(UIImage *)imgSmallAvatar {
    self = [super init];
    if (self) {
        if (strName && (NSNull *)strName != [NSNull null]) {
            personName = strName;
        }
        if (strID && (NSNull *)strID != [NSNull null]) {
            personID = strID ;
        }
        if (imgSmallAvatar && (NSNull *)imgSmallAvatar != [NSNull null]) personSmallAvatar = imgSmallAvatar ;
    }
    return self;    
}

- (id)copy {
    return [super copy];
}

#pragma mark - SDWebImageDownloaderDelegate

- (void)webImageManager:(SDWebImageManager *)imageManager didFinishWithImage:(UIImage *)image {
//    NSLog(@"PersonNodeData; webImageManager; didFinishWithImage");
}

- (void)webImageManager:(SDWebImageManager *)imageManager didFailWithError:(NSError *)error {
//    NSLog(@"PersonNodeData; webImageManager; didFailWithError");
}

@end 

#pragma mark - PersonCategoryData

@implementation PersonCategoryData

@synthesize isChildOfCategory, categoryArray, isHidden, personDeepLevel;

- (id)initWithPersonName:(NSString *)strName
             andPersonID:(NSString *)strID
    andPersonSmallAvatar:(UIImage *)imgSmallAvatar {
    self = [super initWithPersonName:strName andPersonID:strID andPersonSmallAvatar:imgSmallAvatar];
    if (self) {
        personDeepLevel = 0;
        isHidden = NO;
        isChildOfCategory = eHasNotChild;
        categoryArray = [NSMutableArray new];
    }
    return self;    
}

- (void)dealloc {
    [categoryArray removeAllObjects];
    categoryArray = nil;
}

- (enumIsDataAdd)addNode:(PersonNodeData *)node {
    if (!categoryArray) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    if ([categoryArray count] == 0) {
        [categoryArray addObject:node];
        isChildOfCategory = eChildIsNode;
        if (personSmallAvatar == nil && node.personSmallAvatar) {
            personSmallAvatar = node.personSmallAvatar;
        }
        if (personMediumAvatar == nil && node.personMediumAvatar) {
            personMediumAvatar = node.personMediumAvatar;
        }
        if (personLargeAvatar == nil && node.personLargeAvatar) {
            personLargeAvatar = node.personLargeAvatar;
        }
        if (personSmallAvatarURL == nil && node.personSmallAvatarURL) {
            personSmallAvatarURL = node.personSmallAvatarURL;
        }
        if (personMediumAvatarURL == nil && node.personMediumAvatarURL) {
            personMediumAvatarURL = node.personMediumAvatarURL;
        }
        if (personLargeAvatarURL == nil && node.personLargeAvatarURL) {
            personLargeAvatarURL = node.personLargeAvatarURL;
        }
        return eIsDataAddSuccess;
    }
    else
    {
        // MinhPB 2012/10/12
        // OLD
//        if (isChildOfCategory == eChildIsNode) {
//            for (int i=0; i<[categoryArray count]; i++) {
//                PersonNodeData *cjd_Temp = [categoryArray objectAtIndex:i];
//                if ([cjd_Temp.personID isEqualToString:node.personID] ) 
//                    return eIsDataAddHasSameIdInAGroup;
//            }
//            
//            [categoryArray addObject:node];
//            return eIsDataAddSuccess;
//        }
//        else
//            return eIsDataAddFailChildIsCategory;
        
        // MinhPB 2012/10/12
        // For Current
        for (int i=0; i<[categoryArray count]; i++) {
            PersonNodeData *cjd_Temp = [categoryArray objectAtIndex:i];
            if ([cjd_Temp.personID isEqualToString:node.personID] ) 
                return eIsDataAddHasSameIdInAGroup;
        }
        
        if (isChildOfCategory == eChildIsCategory) {
            isChildOfCategory = eChildIsCategoryAndNode;
        }
        [categoryArray addObject:node];
        if (personSmallAvatar == nil && node.personSmallAvatar) {
            personSmallAvatar = node.personSmallAvatar;
        }
        if (personMediumAvatar == nil && node.personMediumAvatar) {
            personMediumAvatar = node.personMediumAvatar;
        }
        if (personLargeAvatar == nil && node.personLargeAvatar) {
            personLargeAvatar = node.personLargeAvatar;
        }
        if (personSmallAvatarURL == nil && node.personSmallAvatarURL) {
            personSmallAvatarURL = node.personSmallAvatarURL;
        }
        if (personMediumAvatarURL == nil && node.personMediumAvatarURL) {
            personMediumAvatarURL = node.personMediumAvatarURL;
        }
        if (personLargeAvatarURL == nil && node.personLargeAvatarURL) {
            personLargeAvatarURL = node.personLargeAvatarURL;
        }
        return eIsDataAddSuccess;
    }
}

- (enumIsDataAdd)addNode:(PersonNodeData *)node atPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    if ([personID isEqualToString:strID]) {
        return [self addNode:node];
    }
    else if (isChildOfCategory == eChildIsCategory || isChildOfCategory == eChildIsCategoryAndNode)
    {
        for (int i=0; i<[categoryArray count]; i++) {
            PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
            enumIsDataAdd jda_Temp = [cjd_Temp addNode:node atPersonID:strID];
            if (jda_Temp == eIsDataAddSearchContinue) 
                continue;
            else
                return jda_Temp;
        }
    }
    return eIsDataAddSearchContinue;
}

- (enumIsDataAdd)addCategory:(PersonCategoryData *)node {
    if (!categoryArray) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    if ([categoryArray count] == 0) {
        [categoryArray addObject:node];
        isChildOfCategory = eChildIsCategory;
        node.personDeepLevel = personDeepLevel + 1;
        if (personSmallAvatar == nil && node.personSmallAvatar) {
            personSmallAvatar = node.personSmallAvatar;
        }
        if (personMediumAvatar == nil && node.personMediumAvatar) {
            personMediumAvatar = node.personMediumAvatar;
        }
        if (personLargeAvatar == nil && node.personLargeAvatar) {
            personLargeAvatar = node.personLargeAvatar;
        }
        if (personSmallAvatarURL == nil && node.personSmallAvatarURL) {
            personSmallAvatarURL = node.personSmallAvatarURL;
        }
        if (personMediumAvatarURL == nil && node.personMediumAvatarURL) {
            personMediumAvatarURL = node.personMediumAvatarURL;
        }
        if (personLargeAvatarURL == nil && node.personLargeAvatarURL) {
            personLargeAvatarURL = node.personLargeAvatarURL;
        }
        return eIsDataAddSuccess;
    }
    else
    {
        // MinhPB 2012/10/12
        // OLD
//        for (int i=0; i<[categoryArray count]; i++) {
//            PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
//            if ([cjd_Temp.personID isEqualToString:node.personID] ) 
//                return eIsDataAddHasSameIdInAGroup;
//        }
//        if (isChildOfCategory == eChildIsCategory) {
//            [categoryArray addObject:node];
//            node.personDeepLevel = personDeepLevel+1;
//            return eIsDataAddSuccess;
//        }
//        else
//            return eIsDataAddFailChildIsNode;
        
        // MinhPB 2012/10/12
        // For Current
        for (int i=0; i<[categoryArray count]; i++) {
            PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
            if ([cjd_Temp.personID isEqualToString:node.personID] ) 
                return eIsDataAddHasSameIdInAGroup;
        }
        
        if (isChildOfCategory == eChildIsNode) {
            isChildOfCategory = eChildIsCategoryAndNode;
        }
        [categoryArray addObject:node];
        node.personDeepLevel = personDeepLevel+1;
        if (personSmallAvatar == nil && node.personSmallAvatar) {
            personSmallAvatar = node.personSmallAvatar;
        }
        if (personMediumAvatar == nil && node.personMediumAvatar) {
            personMediumAvatar = node.personMediumAvatar;
        }
        if (personLargeAvatar == nil && node.personLargeAvatar) {
            personLargeAvatar = node.personLargeAvatar;
        }
        if (personSmallAvatarURL == nil && node.personSmallAvatarURL) {
            personSmallAvatarURL = node.personSmallAvatarURL;
        }
        if (personMediumAvatarURL == nil && node.personMediumAvatarURL) {
            personMediumAvatarURL = node.personMediumAvatarURL;
        }
        if (personLargeAvatarURL == nil && node.personLargeAvatarURL) {
            personLargeAvatarURL = node.personLargeAvatarURL;
        }
        return eIsDataAddSuccess;

    }
}

- (enumIsDataAdd)addCategory:(PersonCategoryData *)node atPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    if ([personID isEqualToString:strID]) {
        return [self addCategory:node];
    }
    else if (isChildOfCategory == eChildIsCategory || isChildOfCategory == eChildIsCategoryAndNode)
    {
        for (int i=0; i<[categoryArray count]; i++) {
            PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
            enumIsDataAdd jda_Temp = [cjd_Temp addCategory:node atPersonID:strID];
            if (jda_Temp == eIsDataAddSearchContinue) 
                continue;
            else
                return jda_Temp;
        }
    }
    return eIsDataAddSearchContinue;
}

- (BOOL)checkImInhere:(PersonNodeData *)node {
    if (isChildOfCategory == eChildIsNode) {
        for (int i=0; i<[categoryArray count]; i++) {
            PersonNodeData *njd_Temp = [categoryArray objectAtIndex:i];
            if ([node.personID isEqualToString:njd_Temp.personID]) {
                return YES;
            }
        }
    }
    return NO;
}

- (enumIsDataRemove)removeCategoriesWithPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if ([((PersonCategoryData *)objTemp).personID isEqualToString:strID]) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonCategoryData *)objTemp).personName);
            }
            else {
                enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeCategoriesWithPersonID:strID];
                if (enumTemp == enumIsDataRemove_Successful) {
                    enumReturn = enumTemp;
                }
                else if (enumTemp == enumIsDataRemove_DataIsNil) {
                    return enumTemp;
                }
            }
        }
    }
    return enumReturn;
}

- (enumIsDataRemove)removePersonWithPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeCategoriesWithPersonID:strID];
            if (enumTemp == enumIsDataRemove_Successful) {
                enumReturn = enumTemp;
            }
            else if (enumTemp == enumIsDataRemove_DataIsNil) {
                return enumTemp;
            }
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if ([((PersonNodeData *)objTemp).personID isEqualToString:strID]) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonNodeData *)objTemp).personName);
            }
        }
    }
    return enumReturn;
}

- (NSMutableArray *)AllCategoriesWithPersonID:(NSString *)strID {
	NSMutableArray *ma_Temp = [NSMutableArray new];
	
    if ([personID isEqualToString:strID]) {
        [ma_Temp addObject:self];
    }
	for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
		if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if ([((PersonCategoryData *)objTemp).personID isEqualToString:strID]) {
                [ma_Temp addObject:objTemp];
            }
            else {
                [ma_Temp addObjectsFromArray:[((PersonCategoryData *)objTemp) AllCategoriesWithPersonID:strID]];
            }
		}
	}
	NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)AllKardsWithPersonID:(NSString *)strID {
	NSMutableArray *ma_Temp = [NSMutableArray new];
	
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
		if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
			[ma_Temp addObjectsFromArray:[((PersonCategoryData *)objTemp) AllKardsWithPersonID:strID]];
		}
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if ([((PersonNodeData *)objTemp).personID isEqualToString:strID]) {
                [ma_Temp addObject:objTemp];
            }
        }
	}
	NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)AllNode {
    NSMutableArray *ma_Temp = [NSMutableArray new];
	
	for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
		if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
			[ma_Temp addObjectsFromArray:((PersonCategoryData *)objTemp).AllNode];
		}
		if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
			[ma_Temp addObject:(PersonNodeData *)objTemp];
		}
	}
	NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)CurrentNode {
    NSMutableArray *ma_Temp = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
        NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            [ma_Temp addObject:objTemp];
        }
    }
	NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)CurrentCategory {
    NSMutableArray *ma_Temp = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
        NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            [ma_Temp addObject:objTemp];
        }
    }
	NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (enumIsDataRemove)removeCategories:(PersonCategoryData *)node {
    if (!node) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
        NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if ((PersonCategoryData *)objTemp == node) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonCategoryData *)objTemp).personName);
            }
            else {
                enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeCategories:node];
                if (enumTemp == enumIsDataRemove_Successful) {
                    enumReturn = enumTemp;
                }
                else if (enumTemp == enumIsDataRemove_DataIsNil) {
                    return enumTemp;
                }
            }
        }
    }
    return enumReturn;
}

- (enumIsDataRemove)removePerson:(PersonNodeData *)node {
    if (!node) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removePerson:node];
            if (enumTemp == enumIsDataRemove_Successful) {
                enumReturn = enumTemp;
            }
            else if (enumTemp == enumIsDataRemove_DataIsNil) {
                return enumTemp;
            }
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if ((PersonNodeData *)objTemp == node) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonNodeData *)objTemp).personName);
            }
        }
    }
    return enumReturn;
}

- (enumIsDataRemove)removeDataFromServer {
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=[categoryArray count]-1; i>=0; i--) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if (((PersonCategoryData *)objTemp).isLocalCopyType == enumIsLocalCopyType_Copy) {
                enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeDataFromServer];
                if (enumTemp == enumIsDataRemove_Successful) {
                    enumReturn = enumTemp;
                }
                else if (enumTemp == enumIsDataRemove_DataIsNil) {
                    return enumTemp;
                }
            }
            else {
                [categoryArray removeObject:objTemp];
            }
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if (((PersonNodeData *)objTemp).isLocalCopyType != enumIsLocalCopyType_Copy) {
                [categoryArray removeObject:objTemp];
            }
        }
    }
    return enumReturn;
}

- (void)resetAllData {
    NSLog(@"categoryArray count:%d",categoryArray.count);
    for (int i=[categoryArray count]-1; i>=0; i--) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            [((PersonCategoryData *)objTemp) resetAllData];
            [categoryArray removeObject:objTemp];
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            [categoryArray removeObject:objTemp];
        }
    }
}

@end

#pragma mark - PersonTableData

@implementation PersonTableData
@synthesize categoryArray;

- (id)init {
    self = [super init];
    if (self) {
		categoryArray = [NSMutableArray new];
	}
	return self;
}

- (void)dealloc {
    [categoryArray removeAllObjects];
    categoryArray = nil;
}

- (enumIsDataRemove)removeCategoriesWithPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if ([((PersonCategoryData *)objTemp).personID isEqualToString:strID]) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonCategoryData *)objTemp).personName);
            }
            else {
                enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeCategoriesWithPersonID:strID];
                if (enumTemp == enumIsDataRemove_Successful) {
                    enumReturn = enumTemp;
                }
                else if (enumTemp == enumIsDataRemove_DataIsNil) {
                    return enumTemp;
                }
            }
        }
    }
    return enumReturn;
}

- (enumIsDataRemove)removePersonWithPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeCategoriesWithPersonID:strID];
            if (enumTemp == enumIsDataRemove_Successful) {
                enumReturn = enumTemp;
            }
            else if (enumTemp == enumIsDataRemove_DataIsNil) {
                return enumTemp;
            }
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if ([((PersonNodeData *)objTemp).personID isEqualToString:strID]) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonNodeData *)objTemp).personName);
            }
        }
    }
    return enumReturn;
}

- (enumIsDataAdd)addNode:(PersonNodeData *)node {
    if (!categoryArray) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    if ([categoryArray count] == 0) {
        [categoryArray addObject:node];
        return eIsDataAddSuccess;
    }
    else
    {
        // MinhPB 2012/10/12
        for (int i=0; i<[categoryArray count]; i++) {
            PersonNodeData *cjd_Temp = [categoryArray objectAtIndex:i];
            if ([cjd_Temp.personID isEqualToString:node.personID] ) 
                return eIsDataAddHasSameIdInAGroup;
        }
        
        [categoryArray addObject:node];
        return eIsDataAddSuccess;
    }
}

- (enumIsDataAdd)addNode:(PersonNodeData *)node atPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    for (int i=0; i<[categoryArray count]; i++) {
        PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
        if ([cjd_Temp.personID isEqualToString:node.personID] ) 
            return eIsDataAddHasSameIdInAGroup;
    }
    for (int i=0; i<[categoryArray count]; i++) {
        PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
        enumIsDataAdd jda_Temp = [cjd_Temp addNode:node atPersonID:strID];
        if (jda_Temp == eIsDataAddSearchContinue) 
            continue;
        else
            return jda_Temp;
    }
    return eIsDataAddSearchFail;
}

- (enumIsDataAdd)addCategory:(PersonCategoryData *)node atPersonID:(NSString *)strID {
    if (!categoryArray || !strID) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    for (int i=0; i<[categoryArray count]; i++) {
        PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
        if ([cjd_Temp.personID isEqualToString:node.personID]) 
            return eIsDataAddHasSameIdInAGroup;
    }
    for (int i=0; i<[categoryArray count]; i++) {
        PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
        enumIsDataAdd jda_Temp = [cjd_Temp addCategory:node atPersonID:strID];
        if (jda_Temp == eIsDataAddSearchContinue) 
            continue;
        else
            return jda_Temp;
    }
    return eIsDataAddSearchFail;
}

- (enumIsDataAdd)addCategory:(PersonCategoryData *)node {
    if (!categoryArray || !node) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    // MinhPB 2012/10/12
    for (int i=0; i<[categoryArray count]; i++) {
        PersonCategoryData *cjd_Temp = [categoryArray objectAtIndex:i];
        if ([cjd_Temp.personID isEqualToString:node.personID]) 
            return eIsDataAddHasSameIdInAGroup;
    }
    
    [categoryArray addObject:node];
    return eIsDataAddSuccess;
}    

- (NSMutableArray *)AllCategoriesWithPersonID:(NSString *)strID {
    NSMutableArray *ma_Return = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
//            NSLog(@"((PersonCategoryData *)objTemp).personID %@", ((PersonCategoryData *)objTemp).personID);
            if ([((PersonCategoryData *)objTemp).personID isEqualToString:strID]) {
                [ma_Return addObject:objTemp];
            }
            else {
                [ma_Return addObjectsFromArray:[((PersonCategoryData *)objTemp) AllCategoriesWithPersonID:strID]];
            }
        }
    }
    return ma_Return;
}

- (NSMutableArray *)AllKardsWithPersonID:(NSString *)strID {
    NSMutableArray *ma_Return = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            [ma_Return addObjectsFromArray:[((PersonCategoryData *)objTemp) AllKardsWithPersonID:strID]];
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if ([((PersonNodeData *)objTemp).personID isEqualToString:strID]) {
                [ma_Return addObject:objTemp];
            }
        }
    }
    return ma_Return;
}

- (NSMutableArray *)AllNode {
    NSMutableArray *ma_Return = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            [ma_Return addObjectsFromArray:((PersonCategoryData *)objTemp).AllNode];
        }
    }
    return ma_Return;
}

- (NSMutableArray *)CurrentNode {
    NSMutableArray *ma_Return = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
        NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            [ma_Return addObject:objTemp];
        }
    }
    return ma_Return;
}

- (NSMutableArray *)CurrentCategory {
    NSMutableArray *ma_Return = [NSMutableArray new];
    
    for (int i=0; i<[categoryArray count]; i++) {
        NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            [ma_Return addObject:objTemp];
        }
    }
    return ma_Return;
}

- (void)resetAllData {
    for (int i=[categoryArray count]-1; i>=0; i--) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            [((PersonCategoryData *)objTemp) resetAllData];
            [categoryArray removeObject:objTemp];
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            [categoryArray removeObject:objTemp];
        }
    }
}

- (enumIsDataRemove)removeCategories:(PersonCategoryData *)node {
    if (!node) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
        NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if ((PersonCategoryData *)objTemp == node) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonCategoryData *)objTemp).personName);
            }
            else {
                enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeCategories:node];
                if (enumTemp == enumIsDataRemove_Successful) {
                    enumReturn = enumTemp;
                }
                else if (enumTemp == enumIsDataRemove_DataIsNil) {
                    return enumTemp;
                }
            }
        }
    }
    return enumReturn;
}

- (enumIsDataRemove)removePerson:(PersonNodeData *)node {
    if (!node) {
        return enumIsDataRemove_DataIsNil;
    }
    
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=0; i<[categoryArray count]; i++) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removePerson:node];
            if (enumTemp == enumIsDataRemove_Successful) {
                enumReturn = enumTemp;
            }
            else if (enumTemp == enumIsDataRemove_DataIsNil) {
                return enumTemp;
            }
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if ((PersonNodeData *)objTemp == node) {
                [categoryArray removeObjectAtIndex:i];
                enumReturn = enumIsDataRemove_Successful;
                NSLog(@"Successful: %@", ((PersonNodeData *)objTemp).personName);
            }
        }
    }
    return enumReturn;
}

- (enumIsDataRemove)removeDataFromServer {
    enumIsDataRemove enumReturn = enumIsDataRemove_NotExist;
    for (int i=[categoryArray count]-1; i>=0; i--) {
		NSObject *objTemp = [categoryArray objectAtIndex:i];
        if ([[objTemp.class description] isEqualToString:[PersonCategoryData.class description]]) {
            if (((PersonCategoryData *)objTemp).isLocalCopyType == enumIsLocalCopyType_Copy) {
                enumIsDataRemove enumTemp = [((PersonCategoryData *)objTemp) removeDataFromServer];
                if (enumTemp == enumIsDataRemove_Successful) {
                    enumReturn = enumTemp;
                }
                else if (enumTemp == enumIsDataRemove_DataIsNil) {
                    return enumTemp;
                }
            }
            else {
                [categoryArray removeObject:objTemp];
            }
        }
        else if ([[objTemp.class description] isEqualToString:[PersonNodeData.class description]]) {
            if (((PersonNodeData *)objTemp).isLocalCopyType != enumIsLocalCopyType_Copy) {
                [categoryArray removeObject:objTemp];
            }
        }
    }
    return enumReturn;
}

@end

#pragma mark - PersonDataManager

@implementation PersonDataManager

- (id)init {
    self = [super init];
    if (self) {
        rootData = [[PersonTableData alloc] init];
    }
    return self;
}

- (enumIsDataAdd)addNode:(PersonNodeData *)node {
    if (!rootData) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    return [rootData addNode:node];
}

- (enumIsDataAdd)addNode:(PersonNodeData *)node atPersonID:(NSString *)strID {
    if (!rootData || !node || !strID) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    return [rootData addNode:node atPersonID:strID];
}

- (enumIsDataAdd)addCategory:(PersonCategoryData *)node {
    if (!rootData) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    return [rootData addCategory:node];
}

- (enumIsDataAdd)addCategory:(PersonCategoryData *)node atPersonID:(NSString *)strID {
    if (!rootData || !node || !strID) {
        return eIsDataAddInvalid;
    }
    if (!node) {
        return eIsDataAddNull;
    }
    if ([node.personID isEqualToString:strID]) {
        return eIsDataAddHasSameIdInAGroup;
    }
    return [rootData addCategory:node atPersonID:strID];
}

- (enumIsDataRemove)removeCategoriesWithPersonID:(NSString *)strID {
    if (!strID) {
        return enumIsDataRemove_DataIsNil;
    }
    return [rootData removeCategoriesWithPersonID:strID];
}

- (enumIsDataRemove)removePersonWithPersonID:(NSString *)strID {
    if (!strID) {
        return enumIsDataRemove_DataIsNil;
    }
    return [rootData removePersonWithPersonID:strID];
}

- (void)dealloc {
    rootData = nil;
}

- (NSMutableArray *)AllCategoriesWithPersonID:(NSString *)strID {
    NSMutableArray *ma_Temp = [rootData AllCategoriesWithPersonID:strID];
//    NSLog(@"rootData.AllKardsHaspersonID = %i",[ma_Temp count]);
    NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)AllKardsWithPersonID:(NSString *)strID {
    NSMutableArray *ma_Temp = [rootData AllKardsWithPersonID:strID];
//    NSLog(@"rootData.AllKardsHaspersonID = %i",[ma_Temp count]);
    NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)AllNode {
    // sort and remove the same id
    NSMutableArray *ma_Temp = rootData.AllNode;
//    NSLog(@"rootData.AllNode = %i",[ma_Temp count]);
    for (int i=0;i<[ma_Temp count];i++) {
        PersonNodeData *njd_Temp1 = [ma_Temp objectAtIndex:i];
        for (int j=i+1;j<[ma_Temp count];j++) {
            PersonNodeData *njd_Temp2 = [ma_Temp objectAtIndex:j];
            if ([njd_Temp1.personID isEqualToString:njd_Temp2.personID]) {
                [ma_Temp removeObjectAtIndex:i];
                i--;
                NSLog(@"contact has the same user id: %@", njd_Temp2.personID);
                continue;
            }
        }
    }
    NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)CurrentNode {
    // sort and remove the same id
    NSMutableArray *ma_Temp = rootData.CurrentNode;
//    NSLog(@"rootData.CurrentNode = %i",[ma_Temp count]);
    NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)CurrentCategory {
    // sort and remove the same id
    NSMutableArray *ma_Temp = rootData.CurrentCategory;
//    NSLog(@"rootData.CurrentCategory = %i",[ma_Temp count]);
    NSMutableArray *ma_Sort = [SupportFunction sortArray:ma_Temp withKey:@"personName"];
    return ma_Sort;
}

- (NSMutableArray *)categoryArray {
    // sort and remove the same id
    NSMutableArray *ma_Temp = rootData.categoryArray;
//    NSLog(@"rootData.categoryArray = %i",[ma_Temp count]);
    return ma_Temp;
}

- (void)resetAllData {
    [rootData resetAllData];
}

- (enumIsDataRemove)removeCategories:(PersonCategoryData *)node {
    if (!node) {
        return enumIsDataRemove_DataIsNil;
    }
    return [rootData removeCategories:node];
}

- (enumIsDataRemove)removePerson:(PersonNodeData *)node {
    if (!node) {
        return enumIsDataRemove_DataIsNil;
    }
    return [rootData removePerson:node];
}

- (enumIsDataRemove)removeDataFromServer {
    return [rootData removeDataFromServer];
}

/////////////////////////////////

static PersonDataManager *_clientShared;
+ (PersonDataManager *)clientShared {
    if ( !_clientShared ) {
        _clientShared = [[PersonDataManager alloc] init];
    }
    return _clientShared;
}

static PersonDataManager *_driverShared;
+ (PersonDataManager *)driverShared {
    if ( !_driverShared ) {
        _driverShared = [[PersonDataManager alloc] init];
    }
    return _driverShared;
}

@end
